package com.dify.knowledge.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dify.knowledge.dto.DifyChatResponse;
import com.dify.knowledge.entity.QuestionRecord;
import com.dify.knowledge.entity.UnansweredQuestion;
import com.dify.knowledge.repository.QuestionRecordMapper;
import com.dify.knowledge.repository.UnansweredQuestionMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 问答服务
 */
@Slf4j
@Service
public class QuestionAnswerService {

    private final DifyService difyService;
    private final QuestionRecordMapper questionRecordMapper;
    private final UnansweredQuestionMapper unansweredQuestionMapper;
    private final ObjectMapper objectMapper;

    public QuestionAnswerService(DifyService difyService,
                                  QuestionRecordMapper questionRecordMapper,
                                  UnansweredQuestionMapper unansweredQuestionMapper,
                                  ObjectMapper objectMapper) {
        this.difyService = difyService;
        this.questionRecordMapper = questionRecordMapper;
        this.unansweredQuestionMapper = unansweredQuestionMapper;
        this.objectMapper = objectMapper;
    }

    /**
     * 处理用户提问
     * 
     * @param question 问题内容
     * @param userId 用户ID
     * @return 问答结果
     */
    @Transactional
    public QuestionAnswerResult askQuestion(String question, Long userId) {
        log.info("处理用户提问，用户ID：{}，问题：{}", userId, question);

        // 调用Dify服务获取答案
        DifyChatResponse difyResponse = difyService.sendChatMessage(question, String.valueOf(userId));
        
        // 判断是否有相关知识
        boolean hasKnowledge = difyService.hasKnowledge(difyResponse);
        
        // 提取知识来源
        String sources = extractSources(difyResponse);
        
        // 保存问答记录
        QuestionRecord record = new QuestionRecord();
        record.setUserId(userId);
        record.setQuestion(question);
        record.setAnswer(difyResponse.getAnswer());
        record.setSources(sources);
        record.setHasKnowledge(hasKnowledge);
        record.setCreatedAt(LocalDateTime.now());
        
        questionRecordMapper.insert(record);
        log.info("问答记录已保存，记录ID：{}", record.getId());
        
        // 如果没有相关知识，创建未解答问题
        if (!hasKnowledge) {
            log.info("知识库中没有相关内容，创建未解答问题");
            createUnansweredQuestion(record.getId());
        }
        
        // 构建返回结果
        QuestionAnswerResult result = new QuestionAnswerResult();
        result.setAnswer(difyResponse.getAnswer());
        result.setSources(sources);
        result.setHasKnowledge(hasKnowledge);
        result.setQuestionRecordId(record.getId());
        result.setSourceList(formatSources(difyResponse));
        
        return result;
    }

    /**
     * 获取问答历史记录
     * 
     * @param page 页码（从1开始）
     * @param size 每页大小
     * @param userId 用户ID（可选，为null时查询所有用户）
     * @return 分页结果
     */
    public Page<QuestionRecord> getHistory(int page, int size, Long userId) {
        log.info("获取问答历史，页码：{}，每页大小：{}，用户ID：{}", page, size, userId);
        
        Page<QuestionRecord> pageParam = new Page<>(page, size);
        
        if (userId != null) {
            // 按用户ID筛选
            return questionRecordMapper.selectByUserId(pageParam, userId);
        } else {
            // 查询所有记录
            return questionRecordMapper.selectPage(pageParam, null);
        }
    }

    /**
     * 创建未解答问题
     * 
     * @param questionRecordId 问答记录ID
     */
    private void createUnansweredQuestion(Long questionRecordId) {
        UnansweredQuestion unansweredQuestion = new UnansweredQuestion();
        unansweredQuestion.setQuestionRecordId(questionRecordId);
        unansweredQuestion.setStatus("PENDING");
        unansweredQuestion.setCreatedAt(LocalDateTime.now());
        
        unansweredQuestionMapper.insert(unansweredQuestion);
        log.info("未解答问题已创建，ID：{}", unansweredQuestion.getId());
    }

    /**
     * 提取知识来源为JSON字符串
     * 
     * @param response Dify响应
     * @return JSON格式的知识来源
     */
    private String extractSources(DifyChatResponse response) {
        try {
            if (response.getMetadata() == null || 
                response.getMetadata().getRetrieverResources() == null ||
                response.getMetadata().getRetrieverResources().isEmpty()) {
                return "[]";
            }
            
            return objectMapper.writeValueAsString(response.getMetadata().getRetrieverResources());
        } catch (JsonProcessingException e) {
            log.error("转换知识来源为JSON失败", e);
            return "[]";
        }
    }
    
    /**
     * 格式化知识来源为列表
     * 
     * @param response Dify响应
     * @return 格式化的知识来源列表
     */
    private java.util.List<SourceInfo> formatSources(DifyChatResponse response) {
        java.util.List<SourceInfo> sourceList = new java.util.ArrayList<>();
        
        if (response.getMetadata() == null || 
            response.getMetadata().getRetrieverResources() == null ||
            response.getMetadata().getRetrieverResources().isEmpty()) {
            return sourceList;
        }
        
        for (DifyChatResponse.RetrieverResource resource : response.getMetadata().getRetrieverResources()) {
            // 截取内容片段（最多100个字符）
            String contentSnippet = resource.getContent();
            if (contentSnippet != null && contentSnippet.length() > 100) {
                contentSnippet = contentSnippet.substring(0, 100) + "...";
            }
            
            SourceInfo sourceInfo = new SourceInfo(
                resource.getDocumentName(),
                resource.getScore(),
                contentSnippet
            );
            sourceList.add(sourceInfo);
        }
        
        return sourceList;
    }

    /**
     * 问答结果DTO
     */
    public static class QuestionAnswerResult {
        private String answer;
        private String sources; // JSON字符串，用于存储到数据库
        private Boolean hasKnowledge;
        private Long questionRecordId;
        private java.util.List<SourceInfo> sourceList; // 格式化的列表，用于返回给前端

        public String getAnswer() {
            return answer;
        }

        public void setAnswer(String answer) {
            this.answer = answer;
        }

        public String getSources() {
            return sources;
        }

        public void setSources(String sources) {
            this.sources = sources;
        }

        public Boolean getHasKnowledge() {
            return hasKnowledge;
        }

        public void setHasKnowledge(Boolean hasKnowledge) {
            this.hasKnowledge = hasKnowledge;
        }

        public Long getQuestionRecordId() {
            return questionRecordId;
        }

        public void setQuestionRecordId(Long questionRecordId) {
            this.questionRecordId = questionRecordId;
        }

        public java.util.List<SourceInfo> getSourceList() {
            return sourceList;
        }

        public void setSourceList(java.util.List<SourceInfo> sourceList) {
            this.sourceList = sourceList;
        }
    }
    
    /**
     * 知识来源信息
     */
    public static class SourceInfo {
        private String documentName;
        private Double score;
        private String content;

        public SourceInfo(String documentName, Double score, String content) {
            this.documentName = documentName;
            this.score = score;
            this.content = content;
        }

        public String getDocumentName() {
            return documentName;
        }

        public void setDocumentName(String documentName) {
            this.documentName = documentName;
        }

        public Double getScore() {
            return score;
        }

        public void setScore(Double score) {
            this.score = score;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}
